#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# @Time: 2020/4/16  20:35
# @Author: 余浪人
# @email: yulangren520@gmail.com
import time
import uuid, zlib, os, math, json
from django.forms import Form
from django.http import JsonResponse
from django.core.paginator import Paginator
from tl_book.settings import BOOK_PATH, BASE_DIR


class DictToObject:
    '''
    字典转对象
    '''

    def __init__(self, **entries):
        self.__dict__.update(entries)


def verify_obj(obj):
    '''
    验证数据有效性
    :param obj: 数据对象或列表
    :return: bool
    '''
    if obj: return True
    # raise Http404


def cleaned_data(raw_data: dict, obj):
    '''
    序列化数据
    :param raw_data:
    :param obj:
    :return:
    '''
    value = {}
    for k, v in raw_data.items():
        if k in dict(obj): value[k] = ''.join(v)
    return value


def error_msg(form: Form):
    '''
    错误错误信息处理
    :param form: form
    :return: 错误信息
    '''
    error = form.errors
    if error and dict(error):
        for _, v in dict(error).items():  return ''.join(v)


def update_data(request, form, model, uuid: str = ''):
    '''
    （修改）更新数据
    :param request: request请求
    :param form: form验证
    :param model: 数据模型
    :return: result
    '''
    f = form(request.POST)
    if f.is_valid():
        obj = model.objects.filter(uuid=uuid)
        data = cleaned_data(dict(request.POST), obj.first())
        try:
            if verify_obj(obj.first()): obj.update(**data)
        except Exception as e:
            return JsonResponse({'code': 4, 'msg': '更新数据异常', 'error': str(e)})
        return JsonResponse({'code': 0, 'msg': '更新数据成功'})
    return JsonResponse({'code': 1, 'msg': '更新数据失败', 'error': error_msg(f)})


def create_data(request, form, model):
    '''
    插入数据
    :param request: request请求
    :param form: form验证
    :param model: 数据模型
    :return: result
    '''
    f = form(request.POST)
    if f.is_valid():
        data = cleaned_data(dict(request.POST), model())
        data.update({'uuid': uuid.uuid4()})
        try:
            model.objects.create(**data)
        except Exception as e:
            return JsonResponse({'code': 4, 'msg': '创建数据异常', 'error': str(e)})
        return JsonResponse({'code': 0, 'msg': '创建数据成功'})
    return JsonResponse({'code': 1, 'msg': '创建数据失败', 'error': error_msg(f)})


def delete_data(uuid, model):
    '''
    删除数据（永久）
    :param uuid: uuid
    :param model: 数据模型
    :return: result
    '''
    try:
        obj = model.objects.filter(uuid=uuid).first()
        if not verify_obj(obj): return JsonResponse({'code': 1, 'msg': '移除数据失败', 'error': '参数有误，未检测到数据'})
        obj.delete()
        return JsonResponse({'code': 0, 'msg': '移除删除数据成功'})
    except Exception as e:
        return JsonResponse({'code': 4, 'msg': '移除数据异常', 'error': str(e)})


def PaginatorPage(request, data_all):
    '''
    系统分页
    :param request: 请求
    :param data_all: 全部数据
    :return:
    '''
    page = request.GET.get('page', '1')
    page_size = request.GET.get('page_size', '20')
    try:
        page = int(page)
    except:
        page = 1
    try:
        page_size = int(page_size)
    except:
        page_size = 20
    all_page = Paginator(data_all, page_size)
    try:
        data = all_page.page(page)
    except:
        data = all_page.page(1)
    return data, all_page


def AcquireUserIp(request):
    '''
    获取访问者IP地址
    :param request: 请求
    :return: IP
    '''
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = ''.join(x_forwarded_for.split(',')[0:1])  # 所以这里是真实的ip
        return ip
    ip = request.META.get('REMOTE_ADDR')  # 这里获得代理ip
    return ip


def lib_compress(text: str):
    '''
    字符串压缩
    :param path: 存储文件路径
    :param text: 需压缩的字符串
    :return: 压缩后字符串文件名称
    '''
    uid = ''.join(str(uuid.uuid4()).split('-')[:1])
    date = time.strftime("%Y-%m-%d", time.localtime())
    path = os.path.join(BASE_DIR,BOOK_PATH,date, f'{uid}.tl').replace('\\','/')
    if not os.path.exists(os.path.dirname(path)):
        os.makedirs(os.path.dirname(path))
    with open(path, 'wb')as fp:
        compress = zlib.compressobj(9)
        fp.write(compress.compress(text.encode('utf-8')))
        fp.write(compress.flush())
        return uid,os.path.join(BOOK_PATH,date).replace('\\','/')

def decompress(path,flieName):
    '''
    对压缩文件进行解压缩
    :param path: 原压缩资源路径
    :param flieName: 原压缩资源文件名
    :return: 解压缩后的东西
    '''
    dst = b''
    n_path = os.path.join(BASE_DIR, path, f'{flieName}.tl').replace('\\', '/')
    try:
        with open(n_path,'rb')as fp:
            decompress = zlib.decompressobj()
            dst += decompress.decompress(fp.read())
            dst += decompress.flush()
            return dst.decode('utf-8')
    except:
        return


def accessor_ip(request):
    '''
    获取访问者IP
    :param request: 请求
    :return: IP
    '''
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = ''.join(x_forwarded_for.split(',')[0:1])  # 所以这里是真实的ip
    else:
        ip = request.META.get('REMOTE_ADDR')  # 这里获得代理ip
    return ip


def access_auto_page(request, data_all):
    '''
    来访者自动分页
    :param request:
    :param data_all:
    :return:
    '''
    page = request.GET.get('page', '1')
    page_size = request.GET.get('page_size', '20')
    try:
        page = int(page)
    except:
        page = 1
    try:
        page_size = int(page_size)
    except:
        page_size = 20
    new_result = data_all[page:(page * page_size) + 1]
    num_page = math.ceil((len(data_all) - 1) / page_size)  # 总页数
    return new_result, {'pages': num_page, 'current': page, 'page_item': list(range(1, num_page + 1))}


def delete_access(conn, key, dbName):
    '''
    移除指定数据库的key
    :param conn: Redis连接
    :param key: key
    :param dbName: 库名
    :return:
    '''
    result = conn.hdel(dbName, key)
    if result: return JsonResponse({'code': 0})
    return JsonResponse({'code': 1, 'msg': '数据不存在或已删除！'})



def categoryList(category_list: list, parent: str = '0'):
    '''
    递归序列化分类数据
    :param category_list: 原始分类
    :param parent: 父级ID
    :return: 数据集 --> list
    '''
    dataList = []
    for u, n, p in category_list:
        if p == str(parent):
            data = {'value': u, 'label': n, 'children': categoryList(category_list, u)}
            if len(data['children']) == 0: data.pop('children')
            dataList.append(data)
    return dataList